﻿#if Xlua


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UFrame;
using XLua;
using System;
using System.IO;

public class XluaMa : Ma<XluaMa>
{
    private XluaMa() { }

    public const string LuaScriptsFolder = "LuaScripts";
    public const string LuaAssetBundleAssetName = "Lua";
    const string GameMainScriptName = "GameMain";
    const string commonMainScriptName = "Common.Main";
    public static bool isEncryption = false;
    private LuaEnv m_XLuaEnv = null;
    private LuaUpdater m_LuaUpdater = null;
    public static string luaPath = "3rdParty/UFrameCode/Xlua/";
    public static string luaABPath = "bawAsset/Xlua/";


    public bool HasGameStart
    {
        get;
        protected set;
    }

    public string AssetbundleName
    {
        get;
        protected set;
    }

    public LuaEnv XLuaEnv
    {
        get
        {
            return m_XLuaEnv;
        }
    }

    protected override void Awake()
    {
        base.Awake();
        AssetbundleName = "lua";
        RegisterEvent(ABLoadCompleteArgs.EventId, OnLoadAB);
    }


    public void OnLoadAB(params object[] args)
    {
        StartGame();
    }

    private void InitLuaEnv()
    {
        m_XLuaEnv = new LuaEnv();
        HasGameStart = false;
        if (m_XLuaEnv != null)
        {
            m_XLuaEnv.AddLoader(CustomLoader);
        }
    }

    public static byte[] CustomLoader(ref string filePath)
    {



        if (GameConfig.I.loadType == PD.ELoadType.Editor)
        {
            filePath = filePath.Replace(".", "/") + ".lua";
            filePath = luaPath + filePath;
            filePath = Path.Combine(Application.dataPath, filePath);
            byte[] b = IOTool.SafeReadAllBytes(filePath);
            return b;
        }
        else if (GameConfig.I.loadType == PD.ELoadType.TestAB || GameConfig.I.loadType == PD.ELoadType.AB)
        {
            //加载AB
            filePath = filePath.Replace(".", "/") + ".bytes";
            filePath = "assets/" + luaABPath + filePath;
        }



        TextAsset asset = ResourcesMa.Load<TextAsset>(filePath);
        if (asset != null)
        {
            byte[] byAry = new byte[asset.bytes.Length];
            Array.Copy(asset.bytes, byAry, byAry.Length);

            if (isEncryption)
            {
                //解密操作
                for (int i = 0; i < byAry.Length; i++)
                {
                    byAry[i]--;
                }
            }
            return byAry;
        }

        PLDebug.LogError(filePath);
        return null;
    }

    protected override void Update()
    {
        base.Update();
        if (m_XLuaEnv != null)
        {
            m_XLuaEnv.Tick();
#if UNITY_ANDROID
                if (Input.GetKeyDown(KeyCode.Escape))
                {
                    SafeDoString("GameMain.OnEscapeApp()");
                }
#endif
            if (Time.frameCount % 100 == 0)
            {
                m_XLuaEnv.FullGc();
            }
        }
    }

    // Lua入口
    public void StartGame()
    {
        InitLuaEnv();
        if (m_XLuaEnv != null)
        {
            LoadScript(GameMainScriptName);
            SafeDoString("GameMain.Start()");
            HasGameStart = true;
        }

        OnInit();
    }

    /// <summary>
    /// 重启Lua模块
    /// 重启虚拟机：热更资源以后被加载的lua脚本可能已经过时，需要重新加载
    /// 最简单和安全的方式是另外创建一个虚拟器，所有东西一概重启
    /// </summary>
    public void Restart()
    {
        Dispose();
        InitLuaEnv();
        OnInit();
    }

    public void SafeDoString(string scriptContent)
    {
        if (m_XLuaEnv != null)
        {
            try
            {
                m_XLuaEnv.DoString(scriptContent);
            }
            catch (System.Exception ex)
            {
                string msg = string.Format("xLua exception : {0}\n {1}\n {2}", ex.Message, ex.StackTrace, scriptContent);
                Debug.LogError(msg, null);
            }
        }
    }

    private void LoadScript(string scriptName)
    {
        SafeDoString(string.Format("require('{0}')", scriptName));
    }


    private void ApplicationQuit()
    {
        if (m_XLuaEnv != null && HasGameStart)
        {
            SafeDoString("GameMain.OnApplicationQuit()");
        }
    }

    public void Dispose()
    {
        if (m_LuaUpdater != null)
        {
            m_LuaUpdater.OnDispose();
        }

        if (m_XLuaEnv != null)
        {
            try
            {
                m_XLuaEnv.Dispose();
                m_XLuaEnv = null;
            }
            catch (System.Exception ex)
            {
                string msg = string.Format("xLua exception : {0}\n {1}", ex.Message, ex.StackTrace);
                // 暂时关闭
                Debug.LogWarning(msg, null);
            }
        }
    }



    // 必须要等待资源管理模块加载Lua AB包以后才能初始化
    public void OnInit()
    {
        if (m_XLuaEnv != null)
        {
            LoadScript(commonMainScriptName);

            m_LuaUpdater = gameObject.GetComponent<LuaUpdater>();
            if (m_LuaUpdater == null)
            {
                m_LuaUpdater = gameObject.AddComponent<LuaUpdater>();
            }
            m_LuaUpdater.OnInit(m_XLuaEnv);
        }
    }

    public LuaEnv GetLuaEnv()
    {
        return m_XLuaEnv;
    }

    //////////////////C#调用Lua 直接调用效率低/////////////////////////////
    //// 直接调用Lua接口
    public void CallFunction(string funcName, params object[] args)
    {
        LuaFunction luaCall = m_XLuaEnv.Global.Get<LuaFunction>(funcName);
        luaCall.Call();
    }

    //失去焦点
    void OnApplicationFocus(bool hasFocus)
    {
        if (m_XLuaEnv == null)
            return;
        LuaFunction luaCall = m_XLuaEnv.Global.Get<LuaFunction>("OnApplicationFocus");
        if (luaCall != null)
            luaCall.Call(hasFocus);
    }
    //暂停游戏
    void OnApplicationPause(bool pauseStatus)
    {

    }

    //退出游戏
    void OnApplicationQuit()
    {
        ApplicationQuit();
    }
}
#endif